package com.itcam.game_.stone;

import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

/**
 * Author:Cammy.Wu
 * Date:2024-06-06
 * Description:
 */

public class StoneMaze extends JFrame implements KeyListener {

    public static void main(String[] args) {
        new StoneMaze();
    }

    int[][] data = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };

    int row; // 0号元素行坐标
    int column; // 0号元素列坐标

    int count = 0; // 初始化步数为0

    public StoneMaze() {
        // 窗体对象.addKeyListener(KeyListener实现类对象);
        this.addKeyListener(this);
        // this : 当前窗体
        // 1) 窗体对象
        // 2) 实现类对象

        // 初始化窗体
        initFrame();
        // 初始化窗体数据
        initData();
        // 绘制游戏界面
        paintView();
        // 设置窗体可见
        setVisible(true);
    }


    // 此方法用户初始化窗体
    public void initFrame() {
        // 设置窗体大小
        setSize(514, 595);
        // 设置窗体关闭模式
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        // 设置窗体标题
        setTitle("石头迷阵1.0版本");
        // 设置窗体居中
        setAlwaysOnTop(true);
        //取消默认布局
        setLayout(null);

//        JLabel jl1 = new JLabel(new ImageIcon("D:\\ProgramData\\image\\javaimage\\8.png"));
//        jl1.setBounds(50, 90, 100, 100);
//        jFrame.getContentPane().add(jl1);
//
//        JLabel jl2 = new JLabel(new ImageIcon("D:\\ProgramData\\image\\javaimage\\8.png"));
//        jl2.setBounds(150, 90, 100, 100);
//        jFrame.getContentPane().add(jl2);
//
//        JLabel jl3= new JLabel(new ImageIcon("D:\\ProgramData\\image\\javaimage\\8.png"));
//        jl3.setBounds(250, 90, 100, 100);
//        jFrame.getContentPane().add(jl3);
//
//        JLabel jl4= new JLabel(new ImageIcon("D:\\ProgramData\\image\\javaimage\\8.png"));
//        jl4.setBounds(350, 90, 100, 100);
//        jFrame.getContentPane().add(jl4);


    }

    // 此方法用户绘制游戏界面
    public void paintView() {
        getContentPane().removeAll();

        if (victory()) {
            // 加载胜利界面
            JLabel winJLabel = new JLabel(new ImageIcon("D:\\ProgramData\\image\\javaimage\\win.png"));
            winJLabel.setBounds(124, 230, 266, 88);
            getContentPane().add(winJLabel);

        }

        JButton jButton = new JButton("重新游戏");
        jButton.setBounds(350, 20, 100, 20);
        getContentPane().add(jButton);
        jButton.setFocusable(false);
        jButton.addActionListener(e -> {
            count = 0;
            initData();
            paintView();
        });

        JLabel jlCount = new JLabel("步数为：" + count);
        jlCount.setBounds(50, 20, 100, 20);
        getContentPane().add(jlCount);

        // 纵
        for (int i = 0; i < 4; i++) {
            // 横
            for (int j = 0; j < 4; j++) {
                JLabel jLabel = new JLabel(new ImageIcon(("D:\\ProgramData\\image\\javaimage\\" + data[i][j] + ".png")));
                jLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
                getContentPane().add(jLabel);
            }

        }

        JLabel background = new JLabel(new ImageIcon("D:\\ProgramData\\image\\javaimage\\background.png"));
        background.setBounds(26, 30, 450, 484);
        getContentPane().add(background);

        getContentPane().repaint();
    }

    // 此方法用于初始化数据
    public void initData() {
        // 准备Random对象
        Random random = new Random();
        // 遍历二维数组获取每一个元素
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                int randomX = random.nextInt(4);
                int randomY = random.nextInt(4);

                int temp = data[i][j];
                data[i][j] = data[randomX][randomY];
                data[randomX][randomY] = temp;
            }
        }

        // 记录0号元素的坐标
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                if (data[i][j] == 0) {
                    row = i;
                    column = j;
                }
            }
        }
    }

    // todo:此方法用于移动业务
    public void move(int keyCode) {
        if (victory()) {
            return;
        }

        if (keyCode == 37) {
            // column == 3 空白块不允许右移
            if (column == 3) {
                return;
            }
            // 空白块和右侧数据交换
            int temp = data[row][column];
            data[row][column] = data[row][column + 1];
            data[row][column + 1] = temp;
            column++;
            count++;
        } else if (keyCode == 38) {
            // row == 3 空白块不允许下移
            if (row == 3) {
                return;
            }
            // 空白块和下侧数据交换
            int temp = data[row][column];
            data[row][column] = data[row + 1][column];
            data[row + 1][column] = temp;
            row++;
            count++;
        } else if (keyCode == 39) {
            // column == 0 空白块不允许左移
            if (column == 0) {
                return;
            }
            // 空白块和左侧数据交换
            int temp = data[row][column];
            data[row][column] = data[row][column - 1];
            data[row][column - 1] = temp;
            column--;
            count++;
        } else if (keyCode == 40) {
            // row == 0 空白块不允许上移
            if (row == 0) {
                return;
            }
            // 空白块和上侧数据交换
            int temp = data[row][column];
            data[row][column] = data[row - 1][column];
            data[row - 1][column] = temp;
            row--;
            count++;
        } else if (keyCode == 90) {
            // 触发作弊器
            data = new int[][]{
                    {1, 2, 3, 4},
                    {5, 6, 7, 8},
                    {9, 10, 11, 12},
                    {13, 14, 15, 0}
            };
        }

    }

    // 此方法判断是否胜利
    public boolean victory() {
        int[][] win = {
                {1, 2, 3, 4},
                {5, 6, 7, 8},
                {9, 10, 11, 12},
                {13, 14, 15, 0}
        };

        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data.length; j++) {
                if (data[i][j] != win[i][j]) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Invoked when a key has been pressed.
     * See the class description for {@link KeyEvent} for a definition of
     * a key pressed event.
     *
     * @param e the event to be processed
     */
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        move(keyCode);
        // 每次移动后，都重新绘制游戏界面
        paintView();
    }

    // ---------------------------------------------------------------------------------------------------------------------

    /**
     * Invoked when a key has been typed.
     * See the class description for {@link KeyEvent} for a definition of
     * a key typed event.
     *
     * @param e the event to be processed
     */
    @Override
    public void keyTyped(KeyEvent e) {

    }


    /**
     * Invoked when a key has been released.
     * See the class description for {@link KeyEvent} for a definition of
     * a key released event.
     *
     * @param e the event to be processed
     */
    @Override
    public void keyReleased(KeyEvent e) {

    }
}
